/**
 * 为数组里的每一个对象填充一个对象
 * @param obj 目标对象 {}
 * @param element 添加的对象 {}
 * @param ignoreKeys 需要忽略的key数组
 * <p>
 *    Object.assign(target, ...sources)
 *    其中，target 是目标对象，sources 是一个或多个源对象。它会返回目标对象 target。
 *    Object.assign() 方法会遍历每个源对象的自有可枚举属性，并将它们复制到目标对象中。
 *    如果多个源对象具有相同的属性名，则后面的源对象的属性会覆盖前面的源对象的属性。如果目标对象中已经存在相同的属性名，则它会被覆盖。
 *    需要注意的是，Object.assign() 方法只会复制源对象的自有可枚举属性，而不会复制其原型链上的属性。
 *    另外，它也不会复制源对象的访问器属性（getter 和 setter）
 * </p>
 */
export function fillObj(obj, element, ...ignoreKeys) {
  for (let i = 0; i < ignoreKeys.length; i++) {
    delete element[ignoreKeys[i]];
  }
  return Object.assign(obj, element);
}

export function fillNode(obj, key, value) {
  let element = {};
  element[key] = value;
  return Object.assign(obj, element);
}

/**
 * 拷贝成一个新对象
 * @param obj 对象
 */
export function copyObj(obj) {
  return {...obj}
}

/**
 * 判断一个对象是否为空
 * @param obj 对象
 * @return
 * null true
 * {} true
 * undefined true
 */
export function isEmpty(obj) {
  return isNull(obj) || obj === '' || !isObj(obj) || toJsonStr(obj) === '{}' || keys(obj).length === 0;
}

export function isNotEmpty(obj) {
  return isEmpty(obj) === false;
}

/**
 * 判断一个对象是否为 null
 * @param obj 对象
 * @return
 * null true
 * undefined true
 * {} false
 */
export function isNullObj(obj) {
  return isNull(obj) && isObj(obj);
}

/**
 * 判断参数是否是对象
 * @param obj 对象
 * @return
 * null false
 * undefined false
 * '123' false
 * 123 false
 * {} true
 */
export function isObj(obj) {
  return Object.prototype.toString.call(obj) === '[object Object]';
}

export function isNotNull(obj) {
  return !isNull(obj);
}

export function isNull(obj) {
  return obj === undefined || typeof obj === 'undefined' || obj === null;
}

export function toJsonStr(obj) {
  return JSON.stringify(obj);
}

export function parseObj(str) {
  return JSON.parse(str);
}

export function keys(obj) {
  return Object.keys(obj);
}


export function isEmptyStr(str) {
  return isNull(str) || str === '' || /^\s*$/.test(str);
}


const regex$ = /\${(.*?)}/g;
/**
 * 字符串格式化
 * @param str  'hello ${name},today is ${week}'
 * @param obj {name:'doudou',week:'Monday'}
 * @return 'hello doudou,today is Monday'
 */
export function strFormat(str, obj) {
    // 使用正则表达式匹配占位符，并替换为对象的属性值
    return str.replace(regex$, (match, p1) => isNull(obj[p1.trim()]) ? match : obj[p1.trim()]);
}

/**
 * 返回占位key
 * @param str  'hello ${name},today is ${week}'
 * @return {name:null,week:null}
 * 使用了正则表达式/\${(.*?)}/g来匹配${}之间的变量名。
 * 然后，使用matchAll()方法获取所有匹配的结果，并遍历每个匹配项，
 * 将变量名作为对象的属性，初始值设为null。最后返回这个对象。
 */
export function strExtract(str) {
  const variables = {};
  for (const match of str.matchAll(regex$)) {
    variables[match[1].trim()] = null;
  }
  return variables;
}

export function equals(var1, var2) {
  return var1 == var2;
}

export function equalsIgnore(var1, var2) {
  return var1.toLowerCase() == var2.toLowerCase();
}

export function notEquals(var1, var2) {
  return !equals(var1, var2);
}

export function notEqualsIgnore(var1, var2) {
  return !equalsIgnore(var1, var2);
}

/**
 * 获取文件后缀
 */
export function getFileType(file) {
  return (file instanceof File) ? file.name.replace(/.+\./, "").toLowerCase() : file.replace(/.+\./, "").toLowerCase();
}

/**
 * 返回一个临时文件的地址
 */
export function createFileUrl(file) {
  return URL.createObjectURL(file.raw);
}

